-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CSHARP-4182: Support for Range Indexes. #988
Conversation
@@ -57,6 +57,7 @@ public class Feature | |||
private static readonly Feature __createIndexCommitQuorum = new Feature("CreateIndexCommitQuorum", WireVersion.Server44); | |||
private static readonly Feature __createIndexesCommand = new Feature("CreateIndexesCommand", WireVersion.Server26); | |||
private static readonly Feature __createIndexesUsingInsertOperations = new Feature("CreateIndexesUsingInsertOperations", WireVersion.Zero, WireVersion.Server42); | |||
private static readonly Feature __csfleRangeExplicitAlgorithm = new Feature("CsfleRangeExplicitAlgorithm", WireVersion.Server62); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe cslfeRange
or cslfeRangeAlgorithm
is sufficient?
I see that simple "range" term is used in most case, also do we expect __csfleRangeImplicitAlgorithm
or similar?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Explicit
in this context means explicit encryption (ie via ClientEncryption). I agree that it's better to remove this part. Will do it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also do we want to call it Preview, to differentiate with future non preview?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At this point I think we will use the same server version guard. Most-likely the only difference will be removing Preview
suffix. I would defer any change here to the time when it will be clear what final shape we will end up here with.
{ | ||
// should not be reached | ||
var butMessage = encryptedValue == null ? " was null" : $"was {encryptedValue.GetType().Name}"; | ||
throw new InvalidOperationException($"The encrypted data must be {typeof(TEncryptedValue).Name}, but {butMessage}."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: could also use: "was {encryptedValue?.GetType()?.Name ?? "null"}"
instead of butMessage
nit: "The encrypted data type must be"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, good point, will do it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
/// For double and decimal128, min/max/precision must all be set, or all be unset. | ||
/// RangeOptions only applies when algorithm is "rangePreview". | ||
/// </remarks> | ||
public class RangeOptions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sealed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
...Driver.Tests/Specifications/client-side-encryption/prose-tests/ClientEncryptionProseTests.cs
Outdated
Show resolved
Hide resolved
...Driver.Tests/Specifications/client-side-encryption/prose-tests/ClientEncryptionProseTests.cs
Show resolved
Hide resolved
{ | ||
var insertPayload6 = ExplicitEncrypt(clientEncryption, encryptOptions, value6, async); | ||
var decryptedValue = ExplicitDecrypt(clientEncryption, insertPayload6, async); | ||
decryptedValue.Should().Be(BsonValue.Create(value6)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Curious why do we need BsonValue.Create
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will double check, maybe it's already not needed. The initial idea (in other tests) is that decryptedValue
is always Bson type, where regularly expected values are just a string or numbers. So when we compare it as is, it fails because of different types. But in this particular case value6
is already bson type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this change is relevant in all other cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
result.Should().BeOfType<BsonDouble>(); | ||
} | ||
break; | ||
case "DoublePrecision": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor: You could combine DoubleNoPrecision and DoublePrecision cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
method is removed
...Driver.Tests/Specifications/client-side-encryption/prose-tests/ClientEncryptionProseTests.cs
Outdated
Show resolved
Hide resolved
@@ -57,6 +57,7 @@ public class Feature | |||
private static readonly Feature __createIndexCommitQuorum = new Feature("CreateIndexCommitQuorum", WireVersion.Server44); | |||
private static readonly Feature __createIndexesCommand = new Feature("CreateIndexesCommand", WireVersion.Server26); | |||
private static readonly Feature __createIndexesUsingInsertOperations = new Feature("CreateIndexesUsingInsertOperations", WireVersion.Zero, WireVersion.Server42); | |||
private static readonly Feature __csfleRangeExplicitAlgorithm = new Feature("CsfleRangeExplicitAlgorithm", WireVersion.Server62); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also do we want to call it Preview, to differentiate with future non preview?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Few minor comments.
var exception = Record.Exception(() => | ||
ExplicitEncrypt( | ||
clientEncryption, | ||
encryptOptions.With(rangeOptions: new RangeOptions(sparsity: 1, min: BsonValue.Create(0), max: BsonValue.Create(200), precision: 2)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think BsonValue.Create
is needed.
You could just pass int
argument and avoid boxing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, it's needed. Since the input type is Optional<BsonValue>
, otherwise, it's not compiled
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, then let's use (BsonValue)0
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer BsonValue.Create
. If you have a factory method, I would use it. NOTE: no huge logic happens behind the scene, it will be almost the same logic as you suggest
"Date" => new BsonDateTime(millisecondsSinceEpoch: value), | ||
"Int" => new BsonInt32(value), | ||
"Long" => new BsonInt64(value), | ||
_ => throw new Exception($"Unsupported rangeSupportedType {rangeSupportedType}.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: $"Unsupported {nameof(rangeSupportedType)} {rangeSupportedType}."
or even better
new ArgumentException($"Unsupported nameof(rangeSupportedType) {rangeSupportedType}.", nameof(rangeSupportedType))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer the first one, since we throw in test in majority of cases only Exception
, done
BsonDocument expression, | ||
bool async) => | ||
async | ||
? clientEncryption.EncryptExpressionAsync(expression, encryptOptions).GetAwaiter().GetResult() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would recommend to shift away from using GetAwaiter().GetResult()
anti-pattern.
You can return task
here, and make the whole test async.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm ok with this approach, but don't really want to change unrelated tests in this file just to make them compiled after this change. So I would use an old approach for this file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this a new method used only by the new RangeExplicitEncryptionTest
test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but this test touches Insert
that then touches everything else
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
discussed offline, changed
var exception = Record.Exception(() => | ||
ExplicitEncrypt( | ||
clientEncryption, | ||
encryptOptions.With(rangeOptions: new RangeOptions(sparsity: 1, min: BsonValue.Create(0), max: BsonValue.Create(200), precision: 2)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, then let's use (BsonValue)0
?
"Date" => new BsonDateTime(millisecondsSinceEpoch: value), | ||
"Int" => new BsonInt32(value), | ||
"Long" => new BsonInt64(value), | ||
_ => throw new Exception($"Unsupported {nameof(rangeSupportedType)} {rangeSupportedType}.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ArgumentException
is used a lot in the driver in such cases already, also it's more suitable exception type her, while Exception
should be used only when there is no better specific exception.
Up to you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's interesting, I expected that we use it rare than it actually happen. We still use: throw new Exception
more often.. but I'm ok to change it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
BsonDocument expression, | ||
bool async) => | ||
async | ||
? clientEncryption.EncryptExpressionAsync(expression, encryptOptions).GetAwaiter().GetResult() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this a new method used only by the new RangeExplicitEncryptionTest
test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
No description provided.